package com.kjcxlab.avcviewer.audio;

import com.kjcxlab.avcviewer.network.UdpReceiver;
import com.kjcxlab.avcviewer.player.IntegrateListener;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;


public class IntegrateAac implements IntegrateListener {

    private AacRtpPacket mPacket = null;
    private UdpReceiver mUdpReceiver = null;
    private ByteArrayOutputStream mFrameStream = null;
    private DataOutputStream mStream = null;
    private ArrayBlockingQueue<byte[]> inQueue = null;
    private int totalByte = 0;  //byte length of received
    private int lSeq = -1;      //last seq
    private int cSeq = -1;      // current seq

    public IntegrateAac(int localPort, ArrayBlockingQueue<byte[]> queue) {
        mPacket = new AacRtpPacket();
        mUdpReceiver = new UdpReceiver(localPort, this);
        mFrameStream = new ByteArrayOutputStream(1024 * 4); // may be not enough
        mStream = new DataOutputStream(mFrameStream);
        this.inQueue = queue;
    }

    public void start() {
        mUdpReceiver.start();
    }

    public void getFrame(byte[] data) throws IOException {

        if (!mPacket.setPacket(data)) {
            return;
        }
        lSeq = cSeq;
        cSeq = mPacket.getSequenceNumber();

        byte[] frame = mPacket.getPayload();
        boolean Mark = mPacket.getMark();
        int headerlen = mPacket.getAuHeaderLength();
        int framelen = mPacket.getFrameLength();
        int datalen = frame.length - 2 - headerlen * 2;

        // Single packet or multi packet
        if (framelen == datalen) {
            int j = 0;
            int len = 0;
            int offset = 2 + headerlen * 2;
            for (j = 0; j < headerlen; j++) {
                len = (((int) (frame[2 + j * 2] & 0xFF) << 5) | ((int) (frame[2 + j * 2 + 1] & 0xFF) >> 3));
                byte[] temp = new byte[len];
                System.arraycopy(frame, offset, temp, 0, len);
                try {
                    inQueue.put(temp);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                offset += len;
                len = 0;
            }
            //Log.d(Constants.AUDIO_TAG, "get a single packet");
        } else if (framelen > datalen && !Mark) {
            // fragment packet
            mFrameStream.reset();
            mStream.write(frame);
            totalByte += datalen;
        } else if (framelen > datalen && !Mark) {
            if (cSeq - lSeq != 1 && cSeq != 0 && lSeq != 65535) {
                totalByte = 0;
                return;
            }
            mStream.write(frame);
            totalByte += datalen;
            // end of one frame all bytes here
            if (totalByte == framelen) {
                try {
                    inQueue.put(mFrameStream.toByteArray());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return;
            }

        }
    }

    @Override
    public void integrateOneFrame(byte[] data) {
        try {
            getFrame(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
